iT邦幫忙

2024 iThome 鐵人賽

DAY 8
1
自我挑戰組

NLP 新手的 30 天入門養成計畫系列 第 8

[Day 8] - 探索句子的本質:句法分析

  • 分享至 

  • xImage
  •  

在前兩天的內容中,我們依序介紹了標註詞性(POS Tagging)和提取實體(NER)的技術,對於探索句子的本質又更近了一步,接下來就可以進入到解析句子結構的主題了!

句法分析 ( syntactic parsing ) 同樣是 NLP 領域中非常重要的主題,它可以完整解析句子的結構,對於語意理解具有關鍵性的作用。

無論中文、英文、日文還是世界上其他的語言,雖然長相不同,用法也不同,但他們大多遵循著一定的結構來將單詞組合成完整的句子。

也因為如此,我們在學習語言的時候才能依據這些文法建立起基本的認知,從而與人交流。

而電腦在解析一個句子的時候,也可以按照同樣的模式,比方說:

Tom tripped and hurt his foot.

這是一個完整的句子,我們不單單可以用 POS 和 NER 標註出他們的詞性和實體,還可以確認哪些單詞是主語、謂語、賓語等,進而畫出整個句子的結構。

我們先拿上次教的 POS 把這個句子標註上詞性:

import spacy

nlp = spacy.load("en_core_web_sm")
sentence = nlp("Tom tripped and hurt his foot.")
print([(token.text, token.tag_) for token in sentence])
[('Tom', 'NNP'), ('tripped', 'VBD'), ('and', 'CC'), ('hurt', 'VB'), ('his', 'PRP$'), ('foot', 'NN'), ('.', '.')]

我們可以按照文法的概念從這張圖去逐層解析整個句子:

https://ithelp.ithome.com.tw/upload/images/20240813/20159088fwZHtdmFl8.png

首先從單詞開始,也就是我們剛剛程式碼所輸出的這些單詞的詞性,像是名詞、動詞或形容詞,他們就是整個句子的結構中最基本的第一層。

接著,我們發現有一些單詞可以組成擁有更豐富意思的短語 ( phrase ),也可以叫做片語,像是名詞短語 ( Noun Phrase, NP )、動詞短語 ( Verb Phrase ) 或形容詞短語 ( Adjectival Phrase, AP )。

如果句子再更複雜一點的話,短語可以再組成子句 ( clause ),也就是包含主詞和動詞但還不是完整句子的一組單詞,包含獨立子句和從屬子句。

按照這個規則一直往上歸納的話,最後可以得到整個句子 ( Sentence, S ),也就是像這個樣子:

https://ithelp.ithome.com.tw/upload/images/20240813/20159088iIUqXTAcFN.png

Constituency Parsing

上述的分析方式就叫做成分句法分析 ( Constituency parsing ),它的想法就是將每個單詞視為句子的一個成分,小成分可以不斷組合成更大的成分,最終組成一個完整的句子。

常用的方法比方說上下文無關文法 ( Context-Free Grammar, CFG ),包含了一套規則,當句子輸入之後,它就會按照規則逐步解析,最終生成完整的句法樹。

那麼就來實際體驗一下吧!

我在網路上找到了好用的套件 benepar,它可以顯示出完整的句法樹,於是我按照官方文件提供的範例和更複雜的句子做了一個小練習:

!python -m spacy download en_core_web_md
!pip install benepar
import nltk
import benepar, spacy

benepar.download('benepar_en3')
nlp = spacy.load('en_core_web_md')
nlp.add_pipe('benepar', config = {'model': 'benepar_en3'})
doc = nlp("Tom stayed home yesterday because he wasn't feeling well.")
sent = list(doc.sents)[0]
print(sent._.parse_string)
(S (NP (NNP Tom)) (VP (VBD stayed) (ADVP (RB home)) (NP (NN yesterday)) (SBAR (IN because) (S (NP (PRP he)) (VP (VBD was) (RB n't) (VP (VBG feeling) (ADVP (RB well))))))) (. .))

從輸出結果可以看到,小括號裡面的成分不斷組合起來,直到最外層的 S 就代表完整的句子。

不過因為它是一行顯示,不容易閱讀,所以我又找了另一個套件 constituent-treelib,它顯示的效果就讓我很滿意了。

!pip install constituent-treelib
from constituent_treelib import ConstituentTree, BracketedTree, Language, Structure

language = Language.English
spacy_model_size = ConstituentTree.SpacyModelSize.Medium
nlp = ConstituentTree.create_pipeline(language, spacy_model_size)

sentence_dyn = "Tom stayed home yesterday because he wasn't feeling well."
tree_dyn = ConstituentTree(sentence_dyn, create_pipeline = True)
tree_dyn

https://ithelp.ithome.com.tw/upload/images/20240813/20159088F6YbIi5NAY.png

Dependency Parsing

剛剛提到的成分句法分析專注在詞性和句法的結構,而依存句法分析 ( Dependency parsing ) 則是專注在單詞之間的聯繫,這種分析方式其實對於我們人類來說更容易理解。

我們對同樣的句子用依存句法分析來畫一棵樹,就會像下面這張圖一樣:

https://ithelp.ithome.com.tw/upload/images/20240813/20159088AbeGrHvXPF.png

  • nsubj 代表 Tom 依存於 tripped,是主詞
  • cc 代表 and 依存於 tripped,是連接詞
  • conj 代表 hurt 依存於 tripped,是協同連接詞
  • dobj 代表 foot 依存於 hurt,是直接賓語
  • poss 代表 his 依存於 foot,是所有格修飾

通過依存句法分析,我們能夠更清楚地理解每個單詞在句子中的角色和他們之間的關係,像是 tripped 用連接詞 and 串接了另一個動詞 hurt,以及 his 用來修飾 foot 等等。

此外,由於 tripped 並沒有其他單詞指向它,所以它就會是這棵樹的 root。

接下來就進入實作吧!

Spacy 本身就有提供 Dependency parsing 的工具,而且程式碼和 NER 很像:

from spacy import displacy

sentence = "Tom tripped and hurt his foot."
doc = nlp(sentence)
displacy.render(doc, style = 'dep', jupyter = True)

https://ithelp.ithome.com.tw/upload/images/20240813/20159088McW481UEY4.png

那麼,對句子的解析就到這裡告一段落,接下來我想要利用這幾天學到的概念 ( 主要是文本前處理 ) 來聊聊關於資訊檢索的知識,然後再進入下一個篇章吧!

推薦文章
詞性標註和句法依存的表示符號
成分句法分析 & 依存句法分析 Parsing 知識圖譜
Constituent Treelib (CTL) Demo
片語、子句、句子是什麼?來一次搞懂!


上一篇
[Day 7] - 探索句子的本質:命名實體辨別
下一篇
[Day 9] - 原來文章是這麼找到的:布林檢索
系列文
NLP 新手的 30 天入門養成計畫30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言